package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPay;
import com.itheima.date.DateUtils;
import com.itheima.mapper.MemberMapper;
import com.itheima.mapper.OrderMapper;
import com.itheima.mapper.OrdersettingMapper;
import com.itheima.pojo.Member;
import com.itheima.pojo.Order;
import com.itheima.service.OrderService;
import com.itheima.wechatpay.MyPayConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service(timeout = 180000)
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    OrdersettingMapper ordersettingMapper;

    @Autowired
    MemberMapper memberMapper;

    @Override
    public Order addOrder(Map map) {
        String orderDate = (String) map.get("orderDate");
        String telephone = (String) map.get("telephone");
        String name = (String) map.get("name");
        String sex = (String) map.get("sex");
        String idCard = (String) map.get("idCard");
        String setmealId = (String) map.get("setmealId");
        String orderType = (String) map.get("orderType");
        System.out.println(orderDate);
        // 查询当日是否预约已满
        int count = ordersettingMapper.isOrderSettingAvailable(orderDate);
        if (count > 0) {
            // 预约未满 可以生成预约订单 在此之前先判断是老用户还是新用户,并保存信息
            Order order = new Order();
            order.setOrderDate(DateUtils.parseString2Date2(orderDate));
            order.setOrderType(orderType);
            order.setOrderStatus("未到诊");
            order.setSetmealId(Integer.parseInt(setmealId));
            QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("PHONENUMBER", telephone);
            Member member = memberMapper.selectOne(queryWrapper);
            if (member == null) {
                // 新用户
                Member newMember = new Member();
                newMember.setName(name);
                newMember.setSex(sex);
                newMember.setIdCard(idCard);
                newMember.setPhoneNumber(telephone);
                newMember.setRegTime(new Date());
                memberMapper.insert(newMember);
                order.setMemberId(newMember.getId());
            } else {
                // 老用户 (可能存在这一天已经预约过了 需要判断)
                int i = baseMapper.findOrderIsExist(member.getId(), orderDate, setmealId);
                if (i > 0) {
                    // 此预约订单已经存在
                    throw new RuntimeException("请勿重复预约");
                } else {
                    // 预约订单不存在
                    order.setMemberId(member.getId());
                }
            }
            baseMapper.insert(order);
            ordersettingMapper.addReservationsByOrderDate(orderDate);
            return order;
        } else {
            throw new RuntimeException("当天预约满了，请改期");
        }
    }

    @Override
    public Map findMemberNameAndSetmealNameAndOrderById(Integer id) {
        Map map = baseMapper.findMemberNameAndSetmealNameAndOrderById(id);
        return map;
    }

    @Override
    public Map<String, String> getPayUrl() {
        Random random = new Random();
        int i = random.nextInt();
        int abs = Math.abs(i);
        String out_trade_no = "202009091r5s"+abs;
        // TODO: 2020/9/8 这个订单号是 需要变化的
        MyPayConfig config = new MyPayConfig();
        //加载微信支付的企业参数
        WXPay wxpay = new WXPay(config);
        //设置微信支付的参数
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "estore商城");
        //订单号,订单号必须唯一。自己测试请切换其他订单号
        data.put("out_trade_no",out_trade_no);
        //设备号，无关
        data.put("device_info", "");
        //币种   人民币
        data.put("fee_type", "CNY");
        //支付金额
        data.put("total_fee", "1");
        data.put("spbill_create_ip", "123.12.12.123");
        //异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。我们不适用异步通知，但是这里的参数必须要有
        data.put("notify_url", "http://www.baidu.com");
        data.put("trade_type", "NATIVE");  // 此处指定为扫码支付
        data.put("product_id", "12");
        try {
            Map<String, String> resp = wxpay.unifiedOrder(data);
            for (Map.Entry<String, String> entry : resp.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println(key + ":" + value);
            }
            HashMap<String,String> map = new HashMap<>();
            map.put("url",resp.get("code_url"));
            map.put("out_trade_no",out_trade_no);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap<String, String>();
        }

    }

    @Override
    public boolean checkOrderStatus(String out_trade_no) {
        MyPayConfig config = new MyPayConfig();
        WXPay wxpay = new WXPay(config);
        //设置需要查询的订单的单号
        Map<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", out_trade_no);
        long start = System.currentTimeMillis();
        long end;
        Map<String, String> resp = new HashMap<>();
        do {
            try {
                Thread.sleep(1000);
                resp = wxpay.orderQuery(data);
            /*
                trade_state代表的就是订单支付结果
                 SUCCESS—支付成功
                 REFUND—转入退款
                 NOTPAY—未支付
                 CLOSED—已关闭
                 REVOKED—已撤销（刷卡支付）
                 USERPAYING--用户支付中
                 PAYERROR--支付失败(其他原因，如银行返回失败)
            */
                for(Map.Entry<String, String> entry:resp.entrySet()){
                    String key = entry.getKey();
                    String value = entry.getValue();
                    System.out.println(key+":"+value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            end = System.currentTimeMillis();

        }while ((end-start)<=50000&&(resp.get("trade_state").equals("NOTPAY")||resp.get("trade_state").equals("USERPAYING")));
        if((end-start)>50000) {
            throw new RuntimeException("超时");
        }else {
            return true;
        }
    }
}
